import os
import sys
import time
import cv2
import numpy as np
import sqlite3
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                             QLabel, QPushButton, QFileDialog, QProgressBar, QListWidget,
                             QListWidgetItem, QMessageBox, QSlider, QSpinBox, QComboBox,
                             QGroupBox, QFormLayout, QTabWidget, QTextEdit, QSplitter, QLineEdit)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QSize
from PyQt5.QtGui import QPixmap, QImage
from scenedetect import VideoManager, SceneManager, StatsManager
from scenedetect.detectors import ContentDetector
from scenedetect.video_splitter import split_video_ffmpeg


# 工作线程，用于处理视频
class VideoProcessingThread(QThread):
    progress_signal = pyqtSignal(int)
    status_signal = pyqtSignal(str)
    finished_signal = pyqtSignal(dict)
    error_signal = pyqtSignal(str)

    def __init__(self, video_path, output_dir, threshold, min_scene_len, format):
        super().__init__()
        self.video_path = video_path
        self.output_dir = output_dir
        self.threshold = threshold
        self.min_scene_len = min_scene_len
        self.format = format

    def run(self):
        try:
            # 确保输出目录存在
            if not os.path.exists(self.output_dir):
                os.makedirs(self.output_dir)

            # 打开视频并获取基本信息
            self.status_signal.emit("分析视频元数据...")
            cap = cv2.VideoCapture(self.video_path)

            if not cap.isOpened():
                raise Exception("无法打开视频文件")

            # 获取视频属性
            fps = cap.get(cv2.CAP_PROP_FPS)
            frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
            width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            duration = frame_count / fps

            cap.release()

            self.status_signal.emit(
                f"视频信息: {width}x{height}@{fps}fps, 总帧数: {frame_count}, 时长: {self.format_time(duration)}")

            # 视频基本信息
            video_info = {
                'path': self.video_path,
                'name': os.path.basename(self.video_path),
                'fps': fps,
                'width': width,
                'height': height,
                'frame_count': frame_count,
                'duration': duration
            }

            # 使用PySceneDetect进行场景检测
            self.status_signal.emit("开始检测场景...")

            # 设置视频管理器
            video_manager = VideoManager([self.video_path])
            stats_manager = StatsManager()
            scene_manager = SceneManager(stats_manager)

            # 添加内容检测器
            scene_manager.add_detector(
                ContentDetector(threshold=self.threshold, min_scene_len=self.min_scene_len)
            )

            # 开始处理视频
            base_timecode = video_manager.get_base_timecode()
            video_manager.set_downscale_factor()

            video_manager.start()

            self.progress_signal.emit(10)  # 固定进度表示开始处理
            self.status_signal.emit("检测场景中...")
            scene_manager.detect_scenes(frame_source=video_manager)  # 不使用回调
            self.progress_signal.emit(50)  # 固定进度表示场景检测完成

            # 获取场景列表
            scene_list = scene_manager.get_scene_list(base_timecode)

            # 关闭视频管理器
            video_manager.release()

            if not scene_list:
                self.status_signal.emit("未检测到任何场景变化，将整个视频视为一个场景")
                scene_list = [(0, frame_count - 1)]

            self.status_signal.emit(f"检测到 {len(scene_list)} 个场景")

            # 创建数据库连接
            db = SceneDatabase("scenes.db")
            video_id = db.add_video(self.video_path, video_info)

            # 提取场景
            self.status_signal.emit("开始提取场景...")
            scenes_info = []
            video_basename = os.path.splitext(os.path.basename(self.video_path))[0]

            # 创建关键帧目录
            keyframes_dir = os.path.join(self.output_dir, f"{video_basename}_keyframes")
            if not os.path.exists(keyframes_dir):
                os.makedirs(keyframes_dir)

            # 处理每个场景
            valid_scenes = []
            for i, scene in enumerate(scene_list):
                # 获取场景的开始和结束时间码
                start_time = scene[0].get_seconds()
                end_time = scene[1].get_seconds()
                duration = end_time - start_time

                # 只保留时长大于0的场景
                if duration <= 0:
                    self.status_signal.emit(f"跳过时长为0的场景 {i + 1}")
                    continue

                valid_scenes.append((i, scene, start_time, end_time, duration))

            # 提取有效场景
            for idx, (i, scene, start_time, end_time, duration) in enumerate(valid_scenes):
                progress = int((idx + 1) / len(valid_scenes) * 100)
                self.progress_signal.emit(progress)

                # 提取场景文件名
                scene_filename = f"{video_basename}_scene_{idx + 1:03d}.{self.format}"
                scene_path = os.path.join(self.output_dir, scene_filename)

                # 使用FFmpeg提取场景片段
                self.status_signal.emit(
                    f"提取场景 {idx + 1}/{len(valid_scenes)}: {self.format_time(start_time)} - {self.format_time(end_time)}")
                os.system(f'ffmpeg -y -loglevel error -i "{self.video_path}" -ss {start_time:.3f} -to {end_time:.3f} '
                          f'-c:v libx264 -c:a aac -strict experimental "{scene_path}"')

                # 提取关键帧（场景中间位置）
                keyframe_filename = f"{video_basename}_scene_{idx + 1:03d}_keyframe.jpg"
                keyframe_path = os.path.join(keyframes_dir, keyframe_filename)

                # 使用FFmpeg提取关键帧
                middle_time = start_time + (duration / 2)
                os.system(f'ffmpeg -y -loglevel error -i "{self.video_path}" -ss {middle_time:.3f} '
                          f'-frames:v 1 "{keyframe_path}"')

                # 确保关键帧存在，如果不存在则从场景文件中提取
                if not os.path.exists(keyframe_path) or os.path.getsize(keyframe_path) == 0:
                    self.status_signal.emit(f"使用场景文件提取关键帧: {scene_path}")
                    # 从场景文件中提取关键帧
                    os.system(f'ffmpeg -y -loglevel error -i "{scene_path}" -ss 0 '
                              f'-frames:v 1 "{keyframe_path}"')

                # 场景信息
                scene_info = {
                    'index': idx,
                    'start_frame': int(start_time * fps),
                    'end_frame': int(end_time * fps),
                    'start_time': start_time,
                    'end_time': end_time,
                    'duration': duration,
                    'file_path': scene_path,
                    'keyframe_path': keyframe_path if os.path.exists(keyframe_path) else None
                }

                # 添加到数据库
                db.add_scene(video_id, idx, scene_info)

                scenes_info.append(scene_info)

            # 返回结果
            result = {
                'video_info': video_info,
                'scenes_info': scenes_info,
                'output_dir': self.output_dir,
                'keyframes_dir': keyframes_dir,
                'video_id': video_id
            }

            self.status_signal.emit("处理完成!")
            self.finished_signal.emit(result)

        except Exception as e:
            import traceback
            self.error_signal.emit(f"处理视频时出错: {str(e)}\n{traceback.format_exc()}")

    def format_time(self, seconds):
        """将秒转换为时:分:秒格式"""
        m, s = divmod(seconds, 60)
        h, m = divmod(m, 60)
        if h > 0:
            return f"{int(h):02d}:{int(m):02d}:{int(s):02d}"
        else:
            return f"{int(m):02d}:{int(s):02d}"


class SceneDatabase:
    """场景数据库管理类"""

    def __init__(self, db_path):
        self.db_path = db_path
        self._init_db()

    def _init_db(self):
        """初始化数据库结构"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()

        # 创建视频表
        cursor.execute('''
        CREATE TABLE IF NOT EXISTS videos (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            file_path TEXT UNIQUE NOT NULL,
            file_name TEXT NOT NULL,
            width INTEGER,
            height INTEGER,
            fps REAL,
            duration REAL,
            frame_count INTEGER,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
        ''')

        # 创建场景表
        cursor.execute('''
        CREATE TABLE IF NOT EXISTS scenes (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            video_id INTEGER NOT NULL,
            scene_index INTEGER NOT NULL,
            start_frame INTEGER NOT NULL,
            end_frame INTEGER NOT NULL,
            start_time REAL NOT NULL,
            end_time REAL NOT NULL,
            duration REAL NOT NULL,
            file_path TEXT,
            keyframe_path TEXT,
            FOREIGN KEY (video_id) REFERENCES videos(id),
            UNIQUE (video_id, scene_index)
        )
        ''')

        conn.commit()
        conn.close()

    def add_video(self, video_path, video_info):
        """添加视频信息到数据库"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()

        cursor.execute('''
        INSERT OR REPLACE INTO videos 
        (file_path, file_name, width, height, fps, duration, frame_count) 
        VALUES (?, ?, ?, ?, ?, ?, ?)
        ''', (
            video_path,
            os.path.basename(video_path),
            video_info.get('width'),
            video_info.get('height'),
            video_info.get('fps'),
            video_info.get('duration'),
            video_info.get('frame_count')
        ))

        video_id = cursor.lastrowid
        conn.commit()
        conn.close()

        return video_id

    def add_scene(self, video_id, scene_index, scene_info):
        """添加场景信息到数据库"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()

        cursor.execute('''
        INSERT OR REPLACE INTO scenes 
        (video_id, scene_index, start_frame, end_frame, start_time, end_time, 
        duration, file_path, keyframe_path) 
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
        ''', (
            video_id,
            scene_index,
            scene_info.get('start_frame'),
            scene_info.get('end_frame'),
            scene_info.get('start_time'),
            scene_info.get('end_time'),
            scene_info.get('duration'),
            scene_info.get('file_path'),
            scene_info.get('keyframe_path')
        ))

        scene_id = cursor.lastrowid
        conn.commit()
        conn.close()

        return scene_id

    def get_video_info(self, video_id=None, video_path=None):
        """获取视频信息"""
        conn = sqlite3.connect(self.db_path)
        conn.row_factory = sqlite3.Row
        cursor = conn.cursor()

        if video_id is not None:
            cursor.execute("SELECT * FROM videos WHERE id = ?", (video_id,))
        elif video_path is not None:
            cursor.execute("SELECT * FROM videos WHERE file_path = ?", (video_path,))
        else:
            conn.close()
            raise ValueError("必须提供video_id或video_path")

        row = cursor.fetchone()
        conn.close()

        if row:
            return dict(row)
        return None

    def get_scenes(self, video_id):
        """获取视频的所有场景"""
        conn = sqlite3.connect(self.db_path)
        conn.row_factory = sqlite3.Row
        cursor = conn.cursor()

        cursor.execute("""
        SELECT * FROM scenes 
        WHERE video_id = ? 
        ORDER BY scene_index
        """, (video_id,))

        scenes = [dict(row) for row in cursor.fetchall()]
        conn.close()

        return scenes

    def get_all_videos(self):
        """获取所有处理过的视频"""
        conn = sqlite3.connect(self.db_path)
        conn.row_factory = sqlite3.Row
        cursor = conn.cursor()

        cursor.execute("SELECT * FROM videos ORDER BY created_at DESC")
        videos = [dict(row) for row in cursor.fetchall()]
        conn.close()

        return videos


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("视频智能镜头切割工具")
        self.setMinimumSize(1000, 700)

        # 初始化UI
        self.init_ui()

        # 初始化数据库
        self.db = SceneDatabase("scenes.db")

        # 加载历史视频列表
        self.load_history_videos()

    def init_ui(self):
        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # 主布局
        main_layout = QVBoxLayout(central_widget)

        # 创建标签页
        self.tab_widget = QTabWidget()
        main_layout.addWidget(self.tab_widget)

        # 添加"切割视频"标签页
        self.create_split_tab()

        # 添加"历史视频"标签页
        self.create_history_tab()

        # 状态栏
        self.statusBar().showMessage("就绪")

    def create_split_tab(self):
        # 创建切割视频标签页
        split_tab = QWidget()
        split_layout = QVBoxLayout(split_tab)

        # 上半部分 - 输入和参数设置
        top_panel = QWidget()
        top_layout = QHBoxLayout(top_panel)

        # 视频选择区域
        input_group = QGroupBox("输入视频")
        input_layout = QVBoxLayout(input_group)

        # 视频路径输入
        path_layout = QHBoxLayout()
        self.video_path_edit = QLineEdit()
        self.video_path_edit.setReadOnly(True)
        self.video_path_edit.setPlaceholderText("选择视频文件...")
        browse_button = QPushButton("浏览...")
        browse_button.clicked.connect(self.browse_video)
        path_layout.addWidget(self.video_path_edit)
        path_layout.addWidget(browse_button)
        input_layout.addLayout(path_layout)

        # 输出目录
        output_layout = QHBoxLayout()
        self.output_dir_edit = QLineEdit()
        self.output_dir_edit.setReadOnly(True)
        self.output_dir_edit.setPlaceholderText("选择输出目录(可选)...")
        browse_output_button = QPushButton("浏览...")
        browse_output_button.clicked.connect(self.browse_output_dir)
        output_layout.addWidget(self.output_dir_edit)
        output_layout.addWidget(browse_output_button)
        input_layout.addLayout(output_layout)

        # 视频预览标签
        self.preview_label = QLabel("视频预览")
        self.preview_label.setAlignment(Qt.AlignCenter)
        self.preview_label.setStyleSheet("background-color: #333; color: #fff;")
        self.preview_label.setMinimumHeight(200)
        input_layout.addWidget(self.preview_label)

        # 添加到顶部布局
        top_layout.addWidget(input_group, 3)

        # 参数设置区域
        param_group = QGroupBox("参数设置")
        param_layout = QFormLayout(param_group)

        # 检测阈值
        threshold_layout = QHBoxLayout()
        self.threshold_slider = QSlider(Qt.Horizontal)
        self.threshold_slider.setRange(10, 60)
        self.threshold_slider.setValue(30)
        self.threshold_value = QLabel("30.0")
        self.threshold_slider.valueChanged.connect(lambda v: self.threshold_value.setText(f"{v:.1f}"))
        threshold_layout.addWidget(self.threshold_slider)
        threshold_layout.addWidget(self.threshold_value)
        param_layout.addRow("场景检测阈值:", threshold_layout)

        # 最小场景长度
        self.min_scene_length = QSpinBox()
        self.min_scene_length.setRange(1, 60)
        self.min_scene_length.setValue(15)
        param_layout.addRow("最小场景长度(帧):", self.min_scene_length)

        # 输出格式
        self.format_combo = QComboBox()
        self.format_combo.addItems(["mp4", "mov", "avi", "mkv"])
        param_layout.addRow("输出格式:", self.format_combo)

        # 开始处理按钮
        self.process_button = QPushButton("开始处理")
        self.process_button.setEnabled(False)
        self.process_button.clicked.connect(self.start_processing)
        param_layout.addRow("", self.process_button)

        # 添加到顶部布局
        top_layout.addWidget(param_group, 2)

        # 添加到主布局
        split_layout.addWidget(top_panel)

        # 下半部分 - 处理进度和结果
        bottom_panel = QWidget()
        bottom_layout = QVBoxLayout(bottom_panel)

        # 处理进度
        progress_layout = QHBoxLayout()
        self.progress_bar = QProgressBar()
        self.progress_bar.setValue(0)
        progress_layout.addWidget(QLabel("处理进度:"))
        progress_layout.addWidget(self.progress_bar)
        bottom_layout.addLayout(progress_layout)

        # 处理状态
        self.status_edit = QTextEdit()
        self.status_edit.setReadOnly(True)
        self.status_edit.setMaximumHeight(100)
        bottom_layout.addWidget(self.status_edit)

        # 结果展示面板(隐藏，处理完成后显示)
        self.result_panel = QWidget()
        self.result_panel.setVisible(False)
        result_layout = QVBoxLayout(self.result_panel)

        # 场景列表
        scenes_group = QGroupBox("检测到的场景")
        scenes_layout = QVBoxLayout(scenes_group)

        self.scene_list = QListWidget()
        self.scene_list.setMinimumHeight(200)
        self.scene_list.itemClicked.connect(self.scene_selected)
        scenes_layout.addWidget(self.scene_list)

        result_layout.addWidget(scenes_group)

        # 场景预览
        preview_group = QGroupBox("场景预览")
        preview_layout = QVBoxLayout(preview_group)

        self.scene_preview = QLabel()
        self.scene_preview.setAlignment(Qt.AlignCenter)
        self.scene_preview.setStyleSheet("background-color: #333; color: #fff;")
        self.scene_preview.setMinimumHeight(200)
        self.scene_preview.setText("选择一个场景查看预览")
        preview_layout.addWidget(self.scene_preview)

        result_layout.addWidget(preview_group)

        bottom_layout.addWidget(self.result_panel)

        # 添加到主布局
        split_layout.addWidget(bottom_panel)

        # 添加到标签页
        self.tab_widget.addTab(split_tab, "切割视频")

    def create_history_tab(self):
        # 创建历史视频标签页
        history_tab = QWidget()
        history_layout = QVBoxLayout(history_tab)

        # 分割器
        splitter = QSplitter(Qt.Horizontal)

        # 视频列表
        videos_panel = QWidget()
        videos_layout = QVBoxLayout(videos_panel)

        videos_layout.addWidget(QLabel("已处理的视频:"))

        self.video_list = QListWidget()
        self.video_list.itemClicked.connect(self.video_selected)
        videos_layout.addWidget(self.video_list)

        splitter.addWidget(videos_panel)

        # 场景列表
        scenes_panel = QWidget()
        scenes_layout = QVBoxLayout(scenes_panel)

        scenes_layout.addWidget(QLabel("视频场景:"))

        self.history_scene_list = QListWidget()
        self.history_scene_list.itemClicked.connect(self.history_scene_selected)
        scenes_layout.addWidget(self.history_scene_list)

        splitter.addWidget(scenes_panel)

        # 场景预览
        preview_panel = QWidget()
        preview_layout = QVBoxLayout(preview_panel)

        preview_layout.addWidget(QLabel("场景预览:"))

        self.history_preview = QLabel()
        self.history_preview.setAlignment(Qt.AlignCenter)
        self.history_preview.setStyleSheet("background-color: #333; color: #fff;")
        self.history_preview.setText("选择一个场景查看预览")
        preview_layout.addWidget(self.history_preview)

        splitter.addWidget(preview_panel)

        # 设置分割比例
        splitter.setSizes([200, 300, 400])

        history_layout.addWidget(splitter)

        # 添加到标签页
        self.tab_widget.addTab(history_tab, "历史视频")

    def browse_video(self):
        file_path, _ = QFileDialog.getOpenFileName(
            self, "选择视频文件", "", "视频文件 (*.mp4 *.mov *.avi *.mkv *.wmv)"
        )
        if file_path:
            self.video_path_edit.setText(file_path)
            self.process_button.setEnabled(True)

            # 更新输出目录
            video_name = os.path.splitext(os.path.basename(file_path))[0]
            default_output = os.path.join(os.path.dirname(file_path), f"{video_name}_scenes")
            self.output_dir_edit.setText(default_output)

            # 显示视频预览
            self.show_video_preview(file_path)

    def browse_output_dir(self):
        dir_path = QFileDialog.getExistingDirectory(self, "选择输出目录")
        if dir_path:
            self.output_dir_edit.setText(dir_path)

    def show_video_preview(self, video_path):
        # 使用OpenCV获取视频第一帧作为预览
        cap = cv2.VideoCapture(video_path)
        ret, frame = cap.read()
        cap.release()

        if ret:
            # 调整尺寸适应预览窗口
            preview_width = self.preview_label.width()
            preview_height = self.preview_label.height()

            h, w, c = frame.shape
            aspect_ratio = w / h

            if preview_width / preview_height > aspect_ratio:
                # 以高度为基准
                new_height = preview_height
                new_width = int(new_height * aspect_ratio)
            else:
                # 以宽度为基准
                new_width = preview_width
                new_height = int(new_width / aspect_ratio)

            # 调整大小
            frame = cv2.resize(frame, (new_width, new_height))

            # 颜色空间转换 BGR -> RGB
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

            # 创建QImage
            q_img = QImage(frame.data, new_width, new_height, new_width * 3, QImage.Format_RGB888)

            # 显示预览图像
            self.preview_label.setPixmap(QPixmap.fromImage(q_img))
        else:
            self.preview_label.setText("无法加载视频预览")

    def start_processing(self):
        # 获取参数
        video_path = self.video_path_edit.text()
        output_dir = self.output_dir_edit.text()
        threshold = self.threshold_slider.value()
        min_scene_length = self.min_scene_length.value()
        format = self.format_combo.currentText()

        # 确保输出目录存在
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)

        # 禁用处理按钮，防止重复点击
        self.process_button.setEnabled(False)

        # 清空状态和进度
        self.status_edit.clear()
        self.progress_bar.setValue(0)
        self.scene_list.clear()
        self.result_panel.setVisible(False)

        # 添加初始状态信息
        self.log_status(f"开始处理视频: {video_path}")
        self.log_status(f"输出目录: {output_dir}")
        self.log_status(f"参数: 阈值={threshold}, 最小场景长度={min_scene_length}帧, 格式={format}")

        # 创建并启动处理线程
        self.processing_thread = VideoProcessingThread(
            video_path, output_dir, threshold, min_scene_length, format
        )

        # 连接信号
        self.processing_thread.progress_signal.connect(self.update_progress)
        self.processing_thread.status_signal.connect(self.log_status)
        self.processing_thread.finished_signal.connect(self.processing_finished)
        self.processing_thread.error_signal.connect(self.processing_error)

        # 启动线程
        self.processing_thread.start()

    def update_progress(self, value):
        # 更新进度条
        self.progress_bar.setValue(value)

    def log_status(self, message):
        # 添加状态信息
        self.status_edit.append(message)
        # 滚动到底部
        cursor = self.status_edit.textCursor()
        cursor.movePosition(cursor.End)
        self.status_edit.setTextCursor(cursor)

    def processing_finished(self, result):
        # 重新启用处理按钮
        self.process_button.setEnabled(True)

        # 记录完成状态
        self.log_status(f"处理完成! 检测到 {len(result['scenes_info'])} 个场景")

        # 更新场景列表
        self.result_panel.setVisible(True)
        self.scene_list.clear()

        # 保存处理结果以供后续使用
        self.current_result = result

        # 添加场景项
        for scene in result['scenes_info']:
            start_time = scene['start_time']
            end_time = scene['end_time']
            duration = scene['duration']

            item = QListWidgetItem(
                f"场景 {scene['index'] + 1}: {self.format_time(start_time)} - {self.format_time(end_time)} (时长: {self.format_time(duration)})")
            item.setData(Qt.UserRole, scene)  # 保存场景信息
            self.scene_list.addItem(item)

        # 加载历史视频列表(如果在历史标签页)
        self.load_history_videos()

    def processing_error(self, error_message):
        # 处理错误
        self.log_status(f"错误: {error_message}")
        self.process_button.setEnabled(True)

        # 显示错误对话框
        QMessageBox.critical(self, "处理错误", error_message)

    def scene_selected(self, item):
        # 获取选中的场景信息
        scene_info = item.data(Qt.UserRole)

        # 显示场景关键帧预览
        if scene_info and 'keyframe_path' in scene_info and scene_info['keyframe_path']:
            keyframe_path = scene_info['keyframe_path']

            # 确保路径是正确的（修复路径中的反斜杠问题）
            keyframe_path = os.path.normpath(keyframe_path)

            # 检查文件是否存在
            if os.path.exists(keyframe_path):
                # 加载并显示关键帧
                pixmap = QPixmap(keyframe_path)

                if not pixmap.isNull():
                    # 保持纵横比调整大小
                    pixmap = pixmap.scaled(
                        self.scene_preview.width(),
                        self.scene_preview.height(),
                        Qt.KeepAspectRatio,
                        Qt.SmoothTransformation
                    )
                    self.scene_preview.setPixmap(pixmap)
                    self.scene_preview.setAlignment(Qt.AlignCenter)
                else:
                    self.scene_preview.setText(f"无法加载关键帧图像")
            else:
                self.scene_preview.setText(f"关键帧文件不存在: {keyframe_path}")
                # 尝试重新生成关键帧
                self.log_status(f"尝试重新生成关键帧...")
                self.regenerate_keyframe(scene_info)
        else:
            self.scene_preview.setText("该场景没有可用的关键帧")

    def regenerate_keyframe(self, scene_info):
        """尝试重新生成关键帧"""
        try:
            # 获取场景视频文件
            scene_path = scene_info.get('file_path')
            if not scene_path or not os.path.exists(scene_path):
                self.log_status(f"无法重新生成关键帧: 场景视频文件不存在")
                return False

            # 获取视频名称和输出目录
            video_basename = os.path.splitext(os.path.basename(self.video_path_edit.text()))[0]
            keyframes_dir = os.path.join(self.output_dir_edit.text(), f"{video_basename}_keyframes")

            # 确保关键帧目录存在
            if not os.path.exists(keyframes_dir):
                os.makedirs(keyframes_dir)

            # 生成新的关键帧路径
            new_keyframe_path = os.path.join(keyframes_dir,
                                             f"{video_basename}_scene_{scene_info['index'] + 1:03d}_keyframe_regen.jpg")

            # 使用FFmpeg从场景视频中提取关键帧
            self.log_status(f"从场景视频提取关键帧: {scene_path}")
            os.system(f'ffmpeg -y -loglevel error -i "{scene_path}" -ss 0 -frames:v 1 "{new_keyframe_path}"')

            # 检查生成的关键帧是否存在
            if os.path.exists(new_keyframe_path) and os.path.getsize(new_keyframe_path) > 0:
                # 更新数据库中的关键帧路径
                if hasattr(self, 'current_result') and 'video_id' in self.current_result:
                    video_id = self.current_result['video_id']
                    scene_info['keyframe_path'] = new_keyframe_path
                    self.db.add_scene(video_id, scene_info['index'], scene_info)

                self.log_status(f"成功重新生成关键帧: {new_keyframe_path}")

                # 更新预览
                pixmap = QPixmap(new_keyframe_path)
                if not pixmap.isNull():
                    pixmap = pixmap.scaled(
                        self.scene_preview.width(),
                        self.scene_preview.height(),
                        Qt.KeepAspectRatio,
                        Qt.SmoothTransformation
                    )
                    self.scene_preview.setPixmap(pixmap)
                    self.scene_preview.setAlignment(Qt.AlignCenter)

                return True
            else:
                self.log_status(f"关键帧生成失败")
                return False

        except Exception as e:
            self.log_status(f"重新生成关键帧时出错: {str(e)}")
            return False

    def load_history_videos(self):
        # 加载历史处理过的视频
        self.video_list.clear()

        videos = self.db.get_all_videos()

        for video in videos:
            item = QListWidgetItem(video['file_name'])
            item.setData(Qt.UserRole, video['id'])  # 保存视频ID
            self.video_list.addItem(item)

    def video_selected(self, item):
        # 获取选中的视频ID
        video_id = item.data(Qt.UserRole)

        # 清空场景列表
        self.history_scene_list.clear()

        # 加载视频场景
        scenes = self.db.get_scenes(video_id)

        # 填充场景列表
        for scene in scenes:
            start_time = scene['start_time']
            end_time = scene['end_time']
            duration = end_time - start_time

            item = QListWidgetItem(
                f"场景 {scene['scene_index'] + 1}: {self.format_time(start_time)} - {self.format_time(end_time)}")
            item.setData(Qt.UserRole, scene)  # 保存场景信息
            self.history_scene_list.addItem(item)

    def history_scene_selected(self, item):
        # 获取场景信息
        scene_data = item.data(Qt.UserRole)

        # 显示关键帧预览
        keyframe_path = scene_data.get('keyframe_path')

        # 确保路径是正确的（修复路径中的反斜杠问题）
        if keyframe_path:
            keyframe_path = os.path.normpath(keyframe_path)

        if keyframe_path and os.path.exists(keyframe_path):
            # 加载并显示关键帧
            pixmap = QPixmap(keyframe_path)

            if not pixmap.isNull():
                # 保持纵横比调整大小
                pixmap = pixmap.scaled(
                    self.history_preview.width(),
                    self.history_preview.height(),
                    Qt.KeepAspectRatio,
                    Qt.SmoothTransformation
                )
                self.history_preview.setPixmap(pixmap)
                self.history_preview.setAlignment(Qt.AlignCenter)
            else:
                self.history_preview.setText("无法加载关键帧图像")
        else:
            # 如果没有关键帧，尝试从场景视频生成
            file_path = scene_data.get('file_path')
            if file_path and os.path.exists(file_path):
                # 尝试重新生成关键帧
                self.history_preview.setText("正在尝试生成关键帧预览...")

                try:
                    # 获取视频ID和场景索引
                    video_id = scene_data.get('video_id')
                    scene_index = scene_data.get('scene_index')

                    # 获取视频名称
                    video_info = self.db.get_video_info(video_id=video_id)
                    video_basename = os.path.splitext(os.path.basename(video_info['file_path']))[0]

                    # 确定关键帧目录
                    output_dir = os.path.dirname(file_path)
                    keyframes_dir = os.path.join(output_dir, f"{video_basename}_keyframes")

                    # 确保关键帧目录存在
                    if not os.path.exists(keyframes_dir):
                        os.makedirs(keyframes_dir)

                    # 生成新的关键帧路径
                    new_keyframe_path = os.path.join(keyframes_dir,
                                                     f"{video_basename}_scene_{scene_index + 1:03d}_keyframe_hist.jpg")

                    # 使用FFmpeg从场景视频中提取关键帧
                    os.system(f'ffmpeg -y -loglevel error -i "{file_path}" -ss 0 -frames:v 1 "{new_keyframe_path}"')

                    # 检查生成的关键帧是否存在
                    if os.path.exists(new_keyframe_path) and os.path.getsize(new_keyframe_path) > 0:
                        # 更新数据库中的关键帧路径
                        scene_data['keyframe_path'] = new_keyframe_path
                        self.db.add_scene(video_id, scene_index, scene_data)

                        # 显示新生成的关键帧
                        pixmap = QPixmap(new_keyframe_path)
                        if not pixmap.isNull():
                            pixmap = pixmap.scaled(
                                self.history_preview.width(),
                                self.history_preview.height(),
                                Qt.KeepAspectRatio,
                                Qt.SmoothTransformation
                            )
                            self.history_preview.setPixmap(pixmap)
                            self.history_preview.setAlignment(Qt.AlignCenter)
                            return

                except Exception as e:
                    self.history_preview.setText(f"生成关键帧失败: {str(e)}")
                    return

            self.history_preview.setText("该场景没有可用的关键帧")

    def format_time(self, seconds):
        """将秒转换为时:分:秒格式"""
        m, s = divmod(seconds, 60)
        h, m = divmod(m, 60)

        if h > 0:
            return f"{int(h):02d}:{int(m):02d}:{int(s):02d}"
        else:
            return f"{int(m):02d}:{int(s):02d}"


# 应用程序入口
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())